package gis.controller;

import bean.common.ModuleConfig;
import bean.common.NavInfo;
import gis.algorithm.GeoPoint;
import gis.algorithm.GeoUtils;
import gis.business.WMSReader;
import gis.common.BaseAuth;
import gis.common.GisConfig;
import gis.core.utils.CoreUtils;
import gis.core.utils.HttpRequest;
import ogc.OGCHelper;
import ogc.wms.WMSGetMapParam;
import ogc.wms.WMSParam;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;

@Controller("mapLoader")
public class MapLoader extends BaseAuth {

    GisConfig gisConfig = GisConfig.GetInstance();
    private static Logger logger = LoggerFactory.getLogger(MapLoader.class);
    String url = "";

    @RequestMapping(value = "/default", method = RequestMethod.GET)
    public ModelAndView GisDefaultPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String m = request.getParameter("m");
        ModelAndView mavAndView = BaseAuth.GetInstance().getModelAndView();
        ModuleConfig module = null;
        String baseUrl = StringUtils.replace(request.getRequestURL().toString(), "/default", "");
        mavAndView.addObject("baseurl", baseUrl);

        if (mavAndView.getViewName() == null || mavAndView.getViewName().equals("")) {
            if (!StringUtils.isBlank(m)) {
                module = gisConfig.getModuleConfig(m);
                mavAndView.setViewName(module.getPage());
                mavAndView.addObject("module", module);
            }
            if (StringUtils.isBlank(m) || module == null) {
                NavInfo navInfo = gisConfig.getNavInfo();
                mavAndView.setViewName(navInfo.getNavPage());
                mavAndView.addObject("nav", navInfo);
                mavAndView.addObject("title", GisConfig.GetInstance().getTitle());
            }
        }
        return mavAndView;
    }

    //@CrossOrigin(origins = "*", maxAge = 3600)
    @RequestMapping(value = {"/mapaction", "/mapaction/{title}/{x}/{y}/{z}", "/mappoiaction", "/mappoiaction/{title}/{x}/{y}/{z}"})
    public void GisMapAction(HttpServletRequest request, HttpServletResponse response) throws IOException {

        url = gisConfig.getArcgisUrl();
        if (gisConfig.getGisType().equals("arcgis")) {
            GetArcgisMap(request, response);
        } else if (gisConfig.getGisType().equals("tiandi")) {
            try {
                GetTiandiMap(request, response);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (gisConfig.getGisType().equals("edushi")) {
            try {
                GetEdushiMap(request, response);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (gisConfig.getGisType().equals("google")) {
            try {
                GetGoogleMap(request, response);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (gisConfig.getGisType().equals("gaode")) {
            if (gisConfig.getIsLoadMap()) {
                GetGaoDeLoacMap(request, response);
            } else {
                GetGaoDeMap(request, response);
            }
        } else if (gisConfig.getGisType().equals("purplishblue")) {
            GetPurplishBlueLoacMap(request, response);
        }

    }

    //@CrossOrigin(origins = "*", maxAge = 3600)
    @RequestMapping(value = {"/mapservice/{gistype}", "/mapservice/{gistype}/{title}/{x}/{y}/{z}"})
    public void GisMapService(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String path = request.getRequestURI();
        String[] p = path.split("/");
        String gistype = gisConfig.getGisType();
        for (String u : p) {
            if (StringUtils.isNotEmpty(u) && StringUtils.contains(u, "gistype_")) {
                gistype = StringUtils.replace(u, "gistype_", "");
                break;
            }
        }

        if (gistype.equals("arcgis")) {
            GetArcgisMap(request, response);
        } else if (gistype.equals("tiandi")) {
            try {
                GetTiandiMap(request, response);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (gistype.equals("edushi")) {
            try {
                GetEdushiMap(request, response);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (gistype.equals("google")) {
            try {
                GetGoogleMap(request, response);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (gistype.equals("gaode")) {
            //GetGaoDeLoacMap(request, response);
            if (gisConfig.getIsLoadMap()) {
                GetGaoDeLoacMap(request, response);
            } else {
                GetGaoDeMap(request, response);
            }
        } else if (gistype.equals("purplishblue")) {
            GetPurplishBlueLoacMap(request, response);
        }

    }

    /**
     * Tiandi
     *
     * @param request
     * @param response
     * @throws Exception
     */
    private void GetTiandiMap(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {
            String path = this.getClass().getResource("/").getPath() + "files/mapaction.tiandi.json";
            String json = CoreUtils.readFile(path);
            response.setContentType("application/json");
            PrintWriter out = null;

            try {
                out = response.getWriter();
                out.write(json);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        } else {
            String path = request.getRequestURI();
            String[] p = path.split("/");
            int row = Integer.parseInt(p[p.length - 2]);
            int level = Integer.parseInt(p[p.length - 3]);
            int col = Integer.parseInt(p[p.length - 1]);

            // 地图
            String url_image_map = "http://t" + col % 8 + ".tianditu.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";
            // poi图层
            String url_image_poi = "http://t" + row % 8 + ".tianditu.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";
            // 2D地图
            String url_image = "http://t" + col % 8 + ".tianditu.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=c&TileMatrix=" + level + "&TileRow=" + row + "&TileCol=" + col + "&style=default&format=tiles";

            //"http://t" + col % 8 + ".tianditu.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";

            //String url_image_map =  "http://t" + col % 8 + ".tianditu.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";

            if (path.contains("mappoiaction")) {
                HttpRequest.GetImage(response, url_image_poi, "image/png");
            } else {
                System.out.println(url_image);
                HttpRequest.GetImage(response, url_image_map, "image/jpg");
            }
        }
    }

    /**
     * Tiandi
     *
     * @param request
     * @param response
     * @throws Exception
     */
    private void GetEdushiMap(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {
            String path = this.getClass().getResource("/").getPath() + "files/arcgis.102100.txt";
            getMapJson(request, response, path);
        } else {
            String path = request.getRequestURI();
            String[] p = path.split("/");
            int row = Integer.parseInt(p[p.length - 2]);
            int level = Integer.parseInt(p[p.length - 3]);
            int col = Integer.parseInt(p[p.length - 1]);

            String url = "";
            int num = 10 - level;
            if (num == 3) {
                //url ="http://cpic2.edushi.com/cn/beijing/zh-chs/mappic/png" + num + "/" + (col-20)+ "","" + (row-20) + ".png";
                url = "http://cpic2.edushi.com/cn/beijing/zh-chs/mappic/png" + num + "/" + (col - 20) + "," + (row - 20) + ".png";
            } else if (num == 2) {
                url = "http://cpic2.edushi.com/cn/beijing/zh-chs/mappic/png" + (num) + "/" + (col - 40) + "," + (row - 40) + ".png";
            } else if (num == 1) {
                url = "http://cpic2.edushi.com/cn/beijing/zh-chs/mappic/png" + (num) + "/" + (col - 80) + "," + (row - 80) + ".png";
            } else {
                url = getBaiduTileUR(level, row, col, "Map");
            }

            HttpRequest.GetImage(response, url, "image/png");
        }
    }

    private String getBaiduTileUR(int level, int row, int col, String mapType) {
        int zoom = level - 1;
        int offsetX = (int) Math.pow(2, zoom);
        int offsetY = offsetX - 1;
        int numX = col - offsetX;
        int numY = (-row) + offsetY;

        zoom = level + 1;
        int num = (col + row) % 8 + 1;
        String url = "";
        if (mapType.equals("Map")) {
            url = "http://online3.map.bdimg.com/tile/?qt=tile&x=" + numX + "&y=" + numY + "&z=" + zoom + "&styles=pl&udt=20140314";
        } else if (mapType.equals("Image")) {
            //url = "http://shangetu3.map.bdimg.com/it/u=x=" + numX + ";y=" + numY + ";z=" + zoom + ";type=sate&fm=46&udt=20140117";
            url = "http://q" + num + ".baidu.com/it/u=x=" + numX + ";y=" + numY + ";z=" + zoom + ";v=009;type=sate&fm=46";
        } else if (mapType.equals("POI")) {
            url = "http://online3.map.bdimg.com/tile/?qt=tile&x=" + numX + "&y=" + numY + "&z=" + zoom + "&styles=sl&v=021&udt=20140314";
        }
        return url;

    }

    /**
     * Google
     *
     * @param request
     * @param response
     * @throws Exception
     */
    private void GetGoogleMap(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {
            String path = this.getClass().getResource("/").getPath() + "files/tileInfo.google.txt";
            getMapJson(request, response, path);
        } else {
            String path = request.getRequestURI();
            String[] p = path.split("/");
            int row = Integer.parseInt(p[p.length - 2]);
            int level = Integer.parseInt(p[p.length - 3]);
            int col = Integer.parseInt(p[p.length - 1]);

            /*// 地图
            String url_image_map = "http://t" + col % 8 + ".tianditu.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";
            // poi图层
            String url_image_poi = "http://t" + row % 8 + ".tianditu.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";
            // 2D地图
            // String url_image = "http://t" + col % 8 +
            // ".tianditu.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=c&TileMatrix="
            // + level + "&TileRow=" + row + "&TileCol=" + col +
            // "&style=default&format=tiles";

            if (path.contains("mappoiaction")) {
                HttpRequest.GetImage(response, url_image_poi, "image/png");
            } else {
                HttpRequest.GetImage(response, url_image_map, "image/jpg");
            }*/
            String url_image_map = getGoogleTileUR(level, row, col, "Map");
            System.out.println(url_image_map);
            HttpRequest.GetImage(response, url_image_map, "image/jpg");
        }
    }

    private String getGoogleTileUR(int level, int row, int col, String mapType) {
        String s = StringUtils.substring("Galileo", 0, ((3 * row + col) % 8)); //"Galileo".Substring(0, ((3 * row + col) % 8));
        String url = "http://mt" + (col % 4) + ".google.cn/vt/lyrs=m@258000000&hl=zh-CN&gl=CN&src=app&x=" + col + "&y=" + row + "&z=" + level + "&" + "s=" + s;

        //一地图
        if (mapType.equals("Map")) {
            //url = "http://mt" + (col % 4) + ".google.cn/vt/lyrs=m@258000000&hl=zh-CN&gl=CN&src=app&x=" + col + "&y=" + row + "&z=" + level + "&" + "s=" + s;
            url = "http://mt1.google.cn/vt/lyrs=m@258000000&hl=zh-CN&gl=CN&src=app&x=" + col + "&y=" + row + "&z=" + level;
        } else if (mapType.equals("Image")) {
            //http://mt0.google.cn/vt/lyrs=s@147&hl=zh-CN&gl=CN&src=app&x=54&y=25&z=6&s=Gal
            url = "http://mt" + (col % 4) + ".google.cn/vt/lyrs=s@147&hl=zh-CN&gl=CN&src=app&x=" + col + "&y=" + row + "&z=" + level + "&s=" + s;
        } else if (mapType.equals("POI")) {
            //http://mt0.google.cn/vt/imgtp=png32&lyrs=h@258000000&hl=zh-CN&gl=CN&src=app&x=50&y=27&z=6&s=G
            url = "http://mt" + (col % 4) + ".google.cn/vt/imgtp=png32&lyrs=h@258000000&hl=zh-CN&gl=CN&src=app&x=" + col + "&y=" + row + "&z=" + level + "&s=" + s;
        }
        return url;
    }

    /**
     * arcgis
     *
     * @param request
     * @param response
     * @throws IOException
     */
    private void GetArcgisMap(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {

            String json = HttpRequest.sendGet(url, "f=json");
            response.setContentType("application/json");
            PrintWriter out = null;

            try {
                out = response.getWriter();
                out.write(json);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        } else {
            String url_image = url + request.getRequestURI().replaceAll("/mapaction", "");
            HttpRequest.GetImage(response, url_image, "image/jpg");
        }
    }

    private void GetGaoDeMap(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {
            //String path = this.getClass().getResource("/").getPath() + "files/arcgis.102100.txt";
            //String path = this.getClass().getResource("/").getPath() + "files/arcgjs.chinaonlinestreetpurplishblue.txt";
            String path = this.getClass().getResource("/").getPath() + "files/arcgis.gaode.txt";
            getMapJson(request, response, path);
        } else {
            String path = request.getRequestURI();
            String[] p = path.split("/");
            int row = Integer.parseInt(p[p.length - 2]);
            int level = Integer.parseInt(p[p.length - 3]);
            int col = Integer.parseInt(p[p.length - 1]);
            String url = "http://webrd0" + (col % 4 + 1) + ".is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=" + col + "&y=" + row + "&z=" + level;
            HttpRequest.GetImage(response, url, "image/png");

            //String url1 = "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer/tile/" + level + "/" + row + "/" + col;
            //HttpRequest.GetImage(response, url1, "image/PNG");
            /*var url = "";
            switch (this.layertype) {
                case "road":
                    url = 'http://webrd0' + (col % 4 + 1) + '.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=' + col + '&y=' + row + '&z=' + level;
                    break;
                case "st":
                    url = 'http://webst0' + (col % 4 + 1) + '.is.autonavi.com/appmaptile?style=6&x=' + col + '&y=' + row + '&z=' + level;
                    break;
                case "label":
                    url = 'http://webst0' + (col % 4 + 1) + '.is.autonavi.com/appmaptile?style=8&x=' + col + '&y=' + row + '&z=' + level;
                    break;
                default:
                    url = 'http://webrd0' + (col % 4 + 1) + '.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=' + col + '&y=' + row + '&z=' + level;
                    break;
            }*/
        }
    }

    private void GetGaoDeLoacMap(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {
            String path = this.getClass().getResource("/").getPath() + "files/arcgis.gaode.txt";
            getMapJson(request, response, path);
        } else {
            String path = request.getRequestURI();
            String[] p = path.split("/");
            int row = Integer.parseInt(p[p.length - 2]);
            int level = Integer.parseInt(p[p.length - 3]);
            int col = Integer.parseInt(p[p.length - 1]);

            String bpath = GisConfig.GetInstance().getBasePath() + "files/gaode/" + level + "/" + col + "_" + row + ".PNG";
            //String bpath = "E:\\Map\\gaodenx\\" + level + "\\" + col + "_" + row + ".PNG";
            //String bpath = "E:\\Map\\gaode\\" + level + "\\" + col + "_" + row + ".PNG";
            FileInputStream is;
            try {
                is = new FileInputStream(bpath);
                int i = is.available(); // 得到文件大小
                byte data[] = new byte[i];
                is.read(data); // 读数据
                is.close();
                response.setContentType("image/png"); // 设置返回的文件类型
                OutputStream toClient = response.getOutputStream(); // 得到向客户端输出二进制数据的对象
                toClient.write(data); // 输出数据
                toClient.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                logger.error("文件没找到：" + bpath + ";" + e.getMessage(), e);
            } catch (IOException e) {
                e.printStackTrace();
                logger.error("IO异常：" + bpath + ";" + e.getMessage(), e);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("异常：" + bpath + ";" + e.getMessage(), e);
            }


        }
    }

    /**
     * 加载本地深色背景图片
     *
     * @param request
     * @param response
     * @throws IOException
     */
    private void GetPurplishBlueLoacMap(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String f = request.getParameter("f");
        if (f != null && "json".endsWith(f)) {
            String path = this.getClass().getResource("/").getPath() + "files/arcgjs.chinaonlinestreetpurplishblue.txt";
            getMapJson(request, response, path);
        } else {
            String path = request.getRequestURI();
            String[] p = path.split("/");
            int level = Integer.parseInt(p[p.length - 3]);
            int row = Integer.parseInt(p[p.length - 2]);
            int col = Integer.parseInt(p[p.length - 1]);

             /*String bpath = "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/"+level+"/"+row+"/"+col;
            HttpRequest.GetImage(response, bpath, "image/png");*/

            //String bpath = "E:\\Map\\purplishblue\\" + level + "\\" + col + "_" + row + ".png";
            String bpath = gisConfig.getBasePath() + "config/purplishblue/" + level + "/" + col + "_" + row + ".png";

            FileInputStream is;
            try {
                is = new FileInputStream(bpath);
                int i = is.available(); // 得到文件大小
                byte data[] = new byte[i];
                is.read(data); // 读数据
                is.close();
                response.setContentType("image/png"); // 设置返回的文件类型
                OutputStream toClient = response.getOutputStream(); // 得到向客户端输出二进制数据的对象
                toClient.write(data); // 输出数据
                toClient.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                logger.error("文件没找到：" + bpath + ";" + e.getMessage(), e);
            } catch (IOException e) {
                e.printStackTrace();
                logger.error("IO异常：" + bpath + ";" + e.getMessage(), e);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("异常：" + bpath + ";" + e.getMessage(), e);
            }
        }
    }

    /**
     * 统一返回json
     *
     * @param request
     * @param response
     */
    private void getMapJson(HttpServletRequest request, HttpServletResponse response, String jsonPath) throws IOException {
        String json = CoreUtils.readFile(jsonPath);
        String callback = request.getParameter("callback");
        if (StringUtils.isNotEmpty(callback)) {
            json = callback + "(" + json + ")";
        }
        response.setContentType("application/json");
        PrintWriter out = null;

        try {
            out = response.getWriter();
            out.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    //@CrossOrigin(origins = "*", maxAge = 3600)
    @RequestMapping(value = {"/dynamicmap", "/dynamicmap/{fun}/{kpi}/{param}"})
    public void GisDynamicMapAction(HttpServletRequest request, HttpServletResponse response) throws Exception {

        WMSParam param = OGCHelper.getWMSParam(request);
        if (param == null) {
            logger.error("dynamicmap参数错误:" + request.toString());
            throw new Exception("wms参数错误");
        }
        if (param instanceof WMSGetMapParam) {
            WMSGetMapParam p = (WMSGetMapParam) param;
            if (p.getCrs().contains("102100")) {
                GeoPoint pmax = GeoUtils.mercatorToLonLat(p.getBbox().getxMax(), p.getBbox().getyMax());
                GeoPoint pmin = GeoUtils.mercatorToLonLat(p.getBbox().getxMin(), p.getBbox().getyMin());
                int a = 0;
                p.getBbox().setxMax(pmax.getX());
                p.getBbox().setyMax(pmax.getY());
                p.getBbox().setxMin(pmin.getX());
                p.getBbox().setyMin(pmin.getY());
            }
            WMSReader r = new WMSReader(request, p);
            BufferedImage image = r.reader();
            Output(response, image);
        }
    }

    /**
     * @param response
     * @param image
     */
    private void Output(HttpServletResponse response, BufferedImage image) {
        response.setContentType("image/png");
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setDateHeader("expires", -1);

        if (image != null) {
            ServletOutputStream output;
            try {
                output = response.getOutputStream();
                ImageIO.write(image, "png", output);
                output.close();
            } catch (IOException e) {
            }
        }
    }

    @RequestMapping(value = "/delete", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    public ModelAndView deleteSchemaAddPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView("/pages/demo.jsp");
        mv.addObject("delete", 1);
        return mv;
    }

}
